﻿using System.Runtime.CompilerServices;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace DimensionsHelper.LanguageService;

public class WorkFolderOptionsPropertyChangedEventArgs(string propertyName)
{
    public string PropertyName { get; } = propertyName;
}

public delegate void WorkFolderOptionsPropertyChangedHandler(WorkFolderOptions sender,
    WorkFolderOptionsPropertyChangedEventArgs e);


public class WorkFolderOptions : IDisposable
{
    [JsonIgnore]
    private readonly string _fileName;

    private readonly FileSystemWatcher _watcher;


    [JsonIgnore]
    private bool _exportMetadataSerializeResult;


    [JsonIgnore]
    private bool _ignoreTypeError;


    [JsonIgnore]
    private string _metadataName = string.Empty;


    [JsonIgnore]
    private List<string> _predefinedMacros = [];

    private bool _saveFileInternal;

    public WorkFolderOptions(string root)
    {
        _fileName = Path.Combine(root, SettingFileName);
        _watcher = new FileSystemWatcher(root)
        {
            EnableRaisingEvents = true,
            NotifyFilter = NotifyFilters.LastWrite,
            Filter = SettingFileName
        };
        _watcher.Changed += OnSettingFileChanged;
        ReadSettingFile();
    }

    /// <summary>
    ///     生成或读取的配置文件名
    /// </summary>
    public static string SettingFileName { get; set; } = "ids_properties.json";

    /// <summary>
    ///     如果在全局忽略类型检查错误，设置此属性为 <see langword="true" />
    /// </summary>
    public bool IgnoreTypeError
    {
        get => _ignoreTypeError;
        set => SetProperty(ref _ignoreTypeError, value);
    }


    /// <summary>
    ///     项目使用的元数据文件路径
    /// </summary>
    public string MetadataName
    {
        get => _metadataName;
        set => SetProperty(ref _metadataName, value);
    }


    /// <summary>
    ///     预定义的宏
    /// </summary>
    public List<string> PredefinedMacros
    {
        get => _predefinedMacros;
        set => SetProperty(ref _predefinedMacros, value);
    }


    /// <summary>
    ///     是否输出元数据序列化后的代码文件
    /// </summary>
    public bool ExportMetadataSerializeResult
    {
        get => _exportMetadataSerializeResult;
        set => SetProperty(ref _exportMetadataSerializeResult, value);
    }


    public void Dispose()
    {
        _watcher.Dispose();
        GC.SuppressFinalize(this);
    }

    public event EventHandler<Exception>? ExceptionOccurred;

    public event WorkFolderOptionsPropertyChangedHandler? PropertyChanged;


    private void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new WorkFolderOptionsPropertyChangedEventArgs(propertyName));
    }


    private void OnSettingFileChanged(object sender, FileSystemEventArgs e)
    {
        if (_saveFileInternal)
        {
            return;
        }

        ReadSettingFile();
    }


    private void ReadSettingFile()
    {
        if (!File.Exists(_fileName))
        {
            return;
        }

        try
        {
            WorkFolderOptions? json = JsonSerializer.Deserialize<WorkFolderOptions>(
                File.ReadAllText(_fileName, Encoding.UTF8),
                ParserOptionsJsonSerializerContext.Default.Options);

            if (json == null)
            {
                return;
            }

            MetadataName = json.MetadataName;
            IgnoreTypeError = json.IgnoreTypeError;
            ExportMetadataSerializeResult = json.ExportMetadataSerializeResult;
        }
        catch (Exception e)
        {
            ExceptionOccurred?.Invoke(this, e);
        }
    }


    /// <summary>
    ///     保存配置文件
    /// </summary>
    private void Save()
    {
        try
        {
            _saveFileInternal = true;
            string value =
                JsonSerializer.Serialize(this, ParserOptionsJsonSerializerContext.Default.WorkFolderOptions);
            File.WriteAllText(_fileName, value);
        }
        catch (Exception e)
        {
            ExceptionOccurred?.Invoke(this, e);
        }
        finally
        {
            _saveFileInternal = false;
        }
    }


    private void SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = "")
    {
        if (EqualityComparer<T>.Default.Equals(field, value))
        {
            return;
        }

        field = value;
        OnPropertyChanged(propertyName);
        Save();
    }
}


[JsonSourceGenerationOptions(
    WriteIndented = true,
    IgnoreReadOnlyFields = true,
    PropertyNameCaseInsensitive = true,
    ReadCommentHandling = JsonCommentHandling.Skip,
    PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
    NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals)]
[JsonSerializable(typeof(WorkFolderOptions))]
public partial class ParserOptionsJsonSerializerContext : JsonSerializerContext;